<?php


namespace app\common;


class WechatPayV3
{
    private $appid;
    private $secret;
    private $mch_id;
    private $key;
    private $serial_no;

    const KEY_LENGTH_BYTE = 32;
    const AUTH_TAG_LENGTH_BYTE = 16;

    protected function _initialize()
    {
        $this->appid = config('xj_mp.appid');//小程序appid
        $this->secret = config('xj_mp.secret');//小程序secret
        $this->mch_id = config('xj_mp.mch_id');//商户id
        $this->key = config('xj_mp.key');//v3key
        $this->serial_no = config('xj_mp.serial_no');//v3序列号
    }
    /**
     * 下单方法
     * @param   $params 下单参数
     */
    public function unifiedOrder($product_type = 1, $openid = '', $phone = '')
    {
        //订单总价
        $total_fee = 79900;
        if ($product_type == 1) {
            $total_fee = 79900;
        }
        if ($product_type == 2) {
            $total_fee = 99900;
        }
        $money = $total_fee;
        $url = "https://api.mch.weixin.qq.com/v3/pay/transactions/jsapi";
        $urlarr = parse_url($url);
        $appid = $this->appid;
        $mchid = $this->mch_id;;//
        $xlid = $this->serial_no;//秘钥序列号
        $data = [];
        $time = time();
        $data['appid'] = $appid;
        $data['mchid'] = $mchid;
        $data['description'] = '描述';//商品描述
        $data['out_trade_no'] = $phone . '_' . time() . '_xingji';//订单编号
        //$data['notify_url'] = $this->request->domain() . "/api/xjmpzl/notify";//回调接口 需根据自己的情况修改
        $data['notify_url'] = $this->request()->domain() . "api/xjmpzl/notify";//回调接口 需根据自己的情况修改
        //$money = 1;
        $data['amount']['total'] = $money;//金额 单位 分
        $data['payer']['openid'] = $openid;//用户openID
        $data = json_encode($data);
        $noncestr = $time;
        $key = $this->getSign($data, $urlarr['path'], $noncestr, $time);//签名
        $token = sprintf('mchid="%s",serial_no="%s",nonce_str="%s",timestamp="%d",signature="%s"', $mchid, $xlid, $noncestr, $time, $key);//头部信息
        $header = [
            'Content-Type:' . 'application/json; charset=UTF-8',
            'Accept:application/json',
            'User-Agent:*/*',
            'Authorization: WECHATPAY2-SHA256-RSA2048 ' . $token
        ];
        $ret = $this->curl_post_https($url, $data, $header);
        $ret = ltrim($ret, '{"prepay_id":"');
        $ret = rtrim($ret, '}"');
        //微信支付（小程序）签名
        $str = $this->getWechartSign($appid, time(), $noncestr, 'prepay_id=' . $ret);
        $arr = [
            'appId' => $appid,
            'timeStamp' => time() . "",
            'package' => 'prepay_id=' . $ret,
            'paySign' => $str,
            'nonceStr' => $noncestr . ""
        ];
        $this->success('success', $arr);
    }


    /**
     * 下单方法
     * @param   $params 下单参数
     */
    public function batches($out_batch_no,$batch_name,$batch_remark)
    {
        //订单总价

        $money = $total_fee;
        $url = "https://api.mch.weixin.qq.com/v3/pay/transactions/jsapi";
        $urlarr = parse_url($url);
        $appid = $this->appid;
        $mchid = $this->mch_id;;//
        $xlid = $this->serial_no;//秘钥序列号
        $data = [];
        $time = time();
        $data = ['out_batch_no'=>$out_batch_no,'batch_name'=>$batch_name,'batch_remark'=>$batch_remark];
        $data = json_encode($data);
        $noncestr = $time;
        $key = $this->getSign($data, $urlarr['path'], $noncestr, $time);//签名
        $token = sprintf('mchid="%s",serial_no="%s",nonce_str="%s",timestamp="%d",signature="%s"', $mchid, $xlid, $noncestr, $time, $key);//头部信息
        $header = [
            'Content-Type:' . 'application/json; charset=UTF-8',
            'Accept:application/json',
            'User-Agent:*/*',
            'Authorization: WECHATPAY2-SHA256-RSA2048 ' . $token
        ];
        $ret = $this->curl_post_https($url, $data, $header);
        $ret = ltrim($ret, '{"prepay_id":"');
        $ret = rtrim($ret, '}"');
        //微信支付（小程序）签名
        $str = $this->getWechartSign($appid, time(), $noncestr, 'prepay_id=' . $ret);
        $arr = [
            'appId' => $appid,
            'timeStamp' => time() . "",
            'package' => 'prepay_id=' . $ret,
            'paySign' => $str,
            'nonceStr' => $noncestr . ""
        ];
        $this->success('success', $arr);
    }

    //微信支付签名
    public function getSign($data = [], $url, $randstr, $time)
    {
        $str = "POST" . "\n" . $url . "\n" . $time . "\n" . $randstr . "\n" . $data . "\n";
        $key = file_get_contents('apiclient_key.pem');//在商户平台下载的秘钥
        $str = $this->getSha256WithRSA($str, $key);
        return $str;
    }

    //调起支付的签名
    public function getWechartSign($appid, $timeStamp, $noncestr, $prepay_id)
    {
        $str = $appid . "\n" . $timeStamp . "\n" . $noncestr . "\n" . $prepay_id . "\n";
        $key = file_get_contents('apiclient_key.pem');
        $str = $this->getSha256WithRSA($str, $key);
        return $str;
    }

    public function getSha256WithRSA($content, $privateKey)
    {
        $binary_signature = "";
        $algo = "SHA256";
        openssl_sign($content, $binary_signature, $privateKey, $algo);
        $sign = base64_encode($binary_signature);
        return $sign;
    }

    /* PHP CURL HTTPS POST */
    public function curl_post_https($url, $data, $header)
    {
        $action = curl_init();
        curl_setopt($action, CURLOPT_URL, $url);
        curl_setopt($action, CURLOPT_CONNECTTIMEOUT, 60);
        curl_setopt($action, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($action, CURLOPT_HEADER, 0);
        curl_setopt($action, CURLOPT_SSL_VERIFYPEER, 0);
        curl_setopt($action, CURLOPT_SSL_VERIFYHOST, 0);
        curl_setopt($action, CURLOPT_POST, 1);
        curl_setopt($action, CURLOPT_POSTFIELDS, $data);
        curl_setopt($action, CURLOPT_HTTPHEADER, $header);
        $result = curl_exec($action);
        curl_close($action);
        return $result;
    }

    /**
     * 异步回调地址
     */
    public function notify()
    {
        //v3 回调需要解密 返回格式与V2也不相同
        //获取返回的xml
        $testxml = file_get_contents("php://input");
        //将xml转化为json格式
        //$jsonxml = json_encode(simplexml_load_string($testxml, 'SimpleXMLElement', LIBXML_NOCDATA));
        //转成数组
        $res = json_decode($testxml, true);
        $decode_data = $res['resource'];
        $associatedData = $decode_data['associated_data'];
        $nonceStr = $decode_data['nonce'];
        $ciphertext = $decode_data['ciphertext'];
        $ciphertext = \base64_decode($ciphertext);
        //解密
        if (PHP_VERSION_ID >= 70100 && in_array('aes-256-gcm', \openssl_get_cipher_methods())) {
            $ctext = substr($ciphertext, 0, -self::AUTH_TAG_LENGTH_BYTE);
            $authTag = substr($ciphertext, -self::AUTH_TAG_LENGTH_BYTE);
            $result = \openssl_decrypt($ctext, 'aes-256-gcm', $this->key, \OPENSSL_RAW_DATA, $nonceStr, $authTag, $associatedData);
        }
        file_log("mp_pay_notify_content.log", $result);
        $result = json_decode($result,true);
        echo '<xml> <return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>';
    }

}